package cn.wolfcode.exception;

import cn.wolfcode.domain.Log;
import cn.wolfcode.mapper.LogMapper;
import cn.wolfcode.util.RequiredPermission;
import cn.wolfcode.util.UserContext;
import com.alibaba.fastjson.JSON;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.validation.support.BindingAwareModelMap;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.Date;

@Component //把当前类注入到spring容器中
@Aspect    //把当前类标识为一个切面供容器读取
public class AopConfig {

    /**
     * 指定切入点
     * 对贴有自定义注解@RequiredPermission的方法，进行切面
     */
    @Pointcut("@annotation(cn.wolfcode.util.RequiredPermission)")
    private void useMethod() {}

    @Autowired
    private HttpServletRequest request;
    @Autowired
    private LogMapper logMapper;

    /**
     * 对切入点进行增强
     */
    @Around(value = "useMethod()")
    public Object recordLog(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("执行之前");
        Object result;
        Log log = new Log();
        log.setName(UserContext.getCurrentUser().getUsername());
        MethodSignature methodSignature = (MethodSignature)proceedingJoinPoint.getSignature();
        Method method = methodSignature.getMethod();
        RequiredPermission annotation = method.getAnnotation(RequiredPermission.class);
        log.setOperation(annotation.name());
        log.setMethod(annotation.expression());
        Object[] args = proceedingJoinPoint.getArgs();
        for (int i = 0; i < args.length; i++) {
            //String name = args[i].getClass().getName();
            if (!(args[i] instanceof BindingAwareModelMap)) {
                log.setArgs(JSON.toJSONString(args[i]));
            }
        }
        Date date = new Date();
        log.setIpAddress(getIpAddress(request));
        log.setCreateTime(date);
        log.setResult(true);
        log.setMsg("无");
        //执行处理方法（执行控制器中的方法）
        try {
            result = proceedingJoinPoint.proceed();
        }catch (Throwable throwable){
            throwable.printStackTrace();
            log.setResult(false);
            log.setMsg(throwable.getMessage());
            throw new Throwable();
        } finally{
            log.setExecutionTime(new Date().getTime() - date.getTime());
            logMapper.insert(log);
        }

        System.out.println("执行之后");
        //result是方法的返回值，直接return回去就会返回给springmvc处理
        return result;
    }

    public static String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }
}